package afcp.alumni.action.base;

import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;

import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.HttpCache;
import net.sourceforge.stripes.action.LocalizableMessage;
import net.sourceforge.stripes.action.Message;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.ajax.JavaScriptResolution;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidationErrors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import afcp.alumni.model.Pb;
import afcp.alumni.model.URL;

// @SessionScope keep actionBean in session. Only one instance of this 
// actionBean is created and kept in session. Normally, a new instance 
// is created for each request.
// http://www.stripesframework.org/display/stripes/Annotation+Reference#AnnotationReference-@SessionScope
// @Wizard Request parameters that are not hidden in page will be automatically added at 
// the end of the form in hidden fields.
// http://www.stripesframework.org/display/stripes/Annotation+Reference#AnnotationReference-@Wizard
// @Session on the complex fields
// http://www.stripesframework.org/display/stripes/Save+ActionBean+fields+in+session
@HttpCache(allow=true, expires=300)
public abstract class BaseAction implements ActionBean {

	private static final Log logger = LogFactory.getLog(BaseAction.class);

	protected MyActionBeanContext context;

	/**
	 * A Stripes action bean includes an {@link ActionBeanContext} object
	 * containing information related to the request and the context. this
	 * object is automatically set and may be accessed using this getter.
	 * 
	 * @return The Stripes {@link ActionBeanContext} object for this action
	 */
	@Override
	public MyActionBeanContext getContext() {
		return context;
	}

	/**
	 * This method is automatically called by Stripes to set the context
	 * property.
	 */
	@Override
	public void setContext(ActionBeanContext context) {
		this.context = (MyActionBeanContext) context;
	}

	public abstract String getUrl();

	/**
	 * Set the default view displayed on this page (this action) by returning a
	 * Stripes {@link Resolution} object. A basic implementation is
	 * <code>return this.toJsp();</code> (use this class method {@link #toJsp()}
	 * )
	 * 
	 * @return A Stripes {@link Resolution} object defining what is sent back to
	 *         the client for this request. You can use a
	 *         {@link ForwardResolution}, a {@link RedirectResolution}, a
	 *         {@link JavaScriptResolution}... Please refer to Stripes
	 *         documentations or Google for more examples.
	 */
	@DefaultHandler
	public abstract Resolution view();

	/**
	 * Returns a {@link RedirectResolution} object to this action. It means that
	 * the answer to this request is an HTTP redirection to this action. It may
	 * be used after sending a POST request to avoid refreshing problems. Be
	 * careful: with this redirection, some of the Stripes treatments can't be
	 * done, like checking the form and displaying error messages with the
	 * {@literal @}{@link Validate} annotation.<br/>
	 * This is a shorthand for
	 * <code>return new RedirectResolution(this.getClass());</code>
	 * 
	 * @return
	 */
	protected Resolution redirect() {
		return new RedirectResolution(this.getClass());
	}

	/**
	 * Shorthand for {@code getContext().forwardToString(url);}
	 * 
	 * @param url
	 *            to render
	 * @return the result rendered as a String
	 * @see {@link MyActionBeanContext#forwardToString(String)}
	 */
	public String forwardToString(String url) {
		return context.forwardToString(url);
	}
	
	public static Message msgObj(String messageKey, Object... parameter) {
		return new LocalizableMessage(messageKey, parameter);
	}
	public String msgToStr(Message message) {
		return message.getMessage(context.getLocale());
	}

	public String msg(String messageKey, Object... parameter) {
		try {
			return new LocalizableMessage(messageKey, parameter)
					.getMessage(context.getLocale());
		} catch (Exception e) {
			logger.error(
					"An error occurred while retrieving the message with key "
							+ messageKey + " with paramters "
							+ Arrays.asList(parameter), e);
			return "ERROR";
		}
	}

	public static String msg(Locale locale, String messageKey,
			Object... parameter) {
		try {
			return new LocalizableMessage(messageKey, parameter)
					.getMessage(locale);
		} catch (Exception e) {
			logger.error(
					"An error occurred while retrieving the message with key "
							+ messageKey + " with paramters "
							+ Arrays.asList(parameter), e);
			return "ERROR";
		}
	}

	public static void addError(ValidationErrors errors, String messageKey, Object... parameter) {
		errors.addGlobalError(new LocalizableError(messageKey, parameter));
	}
	
	public void addFlashScope(String flashScopeKey, String messageKey, Object... parameter) {
		context.getMessages(flashScopeKey).add(new LocalizableMessage(messageKey, parameter));
	}
	public void addFlashScope(String flashScopeKey, Message message) {
		context.getMessages(flashScopeKey).add(message);
	}
	public void addFlashScope(String flashScopeKey, Collection<? extends Message> messages) {
		context.getMessages(flashScopeKey).addAll(messages);
	}
	public void addFlashScope(String messageKey, Object... parameter) {
		context.getMessages(PROBLEM_FLASHSCOPE_KEY).add(new LocalizableMessage(messageKey, parameter));
	}
	public void addFlashScope(Message message) {
		context.getMessages(PROBLEM_FLASHSCOPE_KEY).add(message);
	}
	public void addFlashScope(Collection<? extends Message> messages) {
		context.getMessages(PROBLEM_FLASHSCOPE_KEY).addAll(messages);
	}
	
//	private static final String nullyearvalue = "nullyearvalue";
//	private static final String incorrectyearnumberformat = "incorrectyearnumberformat";
//	private static final String alreadyindatabase = "alreadyindatabase";
//	private static final String incorrectbirthdayformat = "incorrectbirthdayformat";
//	private static final String problemwithdatabase = "problemwithdatabase";
//	private static final String notindatabase = "notindatabase";
//	private static final String nofirstname = "nofirstname";
//	private static final String nolastname = "nolastname";
//	private static final String nobirthdate = "nobirthdate";
//	private static final String noemailquota = "noemailquota";
//	private static final String incorrectsex = "incorrectsex";
//	private static final String passwordalreadygenerated = "passwordalreadygenerated";
//	private static final String problememailsending = "problememailsending";
//	private static final String noemail = "noemail";
//	private static final String noemailcantsend = "noemailcantsend";
//	private static final String noparistechschool = "noparistechschool";
//	private static final String toolongfield = "toolongfield";
//	public static String pbToKey(Pb problem) {
//		return problem.key();
//		
////		String key;
////		switch (problem) {
////		case NULL_YEAR_VALUE:
////			key = nullyearvalue;
////			break;
////		case INCORRECT_YEAR_NUMBER_FORMAT:
////			key = incorrectyearnumberformat;
////			break;
////		case ALREADY_IN_DATABASE:
////			key = alreadyindatabase;
////			break;
////		case INCORRECT_BIRTHDATE_FORMAT:
////			key = incorrectbirthdayformat;
////			break;
////		case PROBLEM_WITH_DATABASE:
////			key = problemwithdatabase;
////			break;
////		case NOT_IN_DATABASE:
////			key = notindatabase;
////			break;
////		case NO_FIRSTNAME:
////			key = nofirstname;
////			break;
////		case NO_LASTNAME:
////			key = nolastname;
////			break;
////		case NO_BIRTHDATE:
////			key = nobirthdate;
////			break;
////		case NO_EMAIL_QUOTA:
////			key = noemailquota;
////			break;
////		case INCORRECT_SEX:
////			key = incorrectsex;
////			break;
////		case PASSWORD_ALREADY_GENERATED:
////			key = passwordalreadygenerated;
////			break;
////		case PROBLEM_EMAIL_SENDING:
////			key = problememailsending;
////			break;
////		case NO_EMAIL:
////			key = noemail;
////			break;
////		case NO_EMAIL_CANT_SEND:
////			key = noemailcantsend;
////			break;
////		case NO_PARISTECH_SCHOOL:
////			key = noparistechschool;
////			break;
////		case TOO_LONG_FIELD:
////			key = toolongfield;
////			break;
////		default:
////			key = "";
////			break;
////		}
////		return key;
//	}
	
//	public static String pbToString(Pb problem, Locale locale) {
//		return msg(locale, pbToKey(problem));
//	}
	
//	public void addProblemsToFlashScope(List<Pb> problems, String flashScopeKey, Object... parameter) {
//		for (Pb problem : problems) {
//			addFlashScope(flashScopeKey, pbToKey(problem), parameter);
//		}
//	}
	
	public static Message pbToMessage(Pb problem, Object... parameter) {
//		return msgObj(pbToKey(problem), parameter);
		return msgObj(problem.key(), parameter);
	}
	
	public static final String PROBLEM_FLASHSCOPE_KEY = "fsproblemkey";
	public String getFlashscopeKey() {
		return PROBLEM_FLASHSCOPE_KEY;
	}
	
//	@After
//	protected void setCurrentPage() {
//		this.context.setCurrentPage(this.getUrl());
//	}
	
	// if needed, get the previous URL :
	
//    public String getLastUrl() { 
//        HttpServletRequest req = getContext().getRequest(); 
//        StringBuilder sb = new StringBuilder(); 
//
//        // Start with the URI and the path 
//        String uri = (String) 
//            req.getAttribute("javax.servlet.forward.request_uri"); 
//        String path = (String) 
//            req.getAttribute("javax.servlet.forward.path_info"); 
//        if (uri == null) { 
//            uri = req.getRequestURI(); 
//            path = req.getPathInfo(); 
//        } 
//        sb.append(uri); 
//        if (path != null) { sb.append(path); } 
//
//        // Now the request parameters 
//        sb.append('?'); 
//        Map<String,String[]> map = 
//            new HashMap<String,String[]>(req.getParameterMap()); 
//
//        // Remove previous locale parameter, if present. 
//        map.remove(MyLocalePicker.LOCALE); 
//
//        // Append the parameters to the URL 
//        for (String key : map.keySet()) { 
//            String[] values = map.get(key); 
//            for (String value : values) { 
//                sb.append(key).append('=').append(value).append('&'); 
//            } 
//        } 
//        // Remove the last '&' 
//        sb.deleteCharAt(sb.length() - 1); 
//
//        return sb.toString(); 
//    }

	private URL currentUrl = null;
	public URL getCurrentUrl() {
		if (currentUrl == null) {
			currentUrl = new URL(getUrl(), context.getRequest().getQueryString());
		}
		return currentUrl;
	}

}
